package com.kgc.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.kgc.api.goods.GoodsItemApi;
import com.kgc.api.goods.HotWordApi;
import com.kgc.api.goods.NewProductApi;
import com.kgc.bean.GoodsItem;
import com.kgc.bean.HotWord;
import com.kgc.constant.ElsConstant;
import com.kgc.form.ElasticsearchGoodsResult;
import com.kgc.service.ElasticsearchService;
import com.kgc.util.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * Created on 2021/6/21.
 * Author: lzy
 * Description:  业务实现层
 */
@Service
@Slf4j
public class ElasticsearchServiceImpl implements ElasticsearchService {

    @Autowired(required = false)
    private RestHighLevelClient restHighLevelClient;

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Autowired
    private RedisUtils redisUtils;

    @Reference(timeout = 30000)
    private HotWordApi hotWordApi;

    @Reference(timeout = 30000)
    private NewProductApi newProductApi;

    @Reference(timeout = 30000)
    private GoodsItemApi goodsItemApi;


    @Override
    public List<ElasticsearchGoodsResult> elsearchHighlightPage(String keyword, Integer pageNo, Integer pageSize) throws IOException {
       // log.info("查询的页码：{}",pageNo);
        int num = (pageNo-1)*pageSize;
        if(num < 1){
            num = 0;
        }

        // 创建搜索
        SearchRequest searchRequest = new SearchRequest(ElsConstant.ElS_SEARCH_INDEX);
        // 高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field(keyword);
        highlightBuilder.requireFieldMatch(false);
        highlightBuilder.preTags("<span style='color:red'>");
        highlightBuilder.postTags("</span>");

        // 构建搜索条件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
                .query(QueryBuilders.matchQuery(ElsConstant.ElS_SEARCH_FIELDS,keyword))
                .from(num)
                .size(pageSize)
                .timeout(new TimeValue(60, TimeUnit.SECONDS))
                .highlighter(highlightBuilder);
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        List<ElasticsearchGoodsResult> list = new LinkedList<>();

        for (SearchHit hit : searchResponse.getHits().getHits()){
            ElasticsearchGoodsResult elasticsearchGoodsResult = JSONObject.parseObject(hit.getSourceAsString(),ElasticsearchGoodsResult.class);

            // 处理高亮显示的结果
            HighlightField titleField = hit.getHighlightFields().get(ElsConstant.ElS_SEARCH_FIELDS);
            if (titleField != null) {
                elasticsearchGoodsResult.setGoodsName(titleField.getFragments()[0].toString());
            }

            list.add(elasticsearchGoodsResult);
        }
        return list;
    }

    @Async("asyncServiceExecutor")
    @Override
    public void hotwordZincrby(String hotword) {
        redisTemplate.opsForZSet().incrementScore(ElsConstant.HOT_WORD_DATABASE,hotword,ElsConstant.HOT_WORD_STEP);
    }

    @Override
    public List<HotWord> querySelectHotWord5() {
        // 到数据库里面去获取搜索量最多的五条数据
        List<HotWord> list = hotWordApi.selectHotWord5();
       //  Set<ZSetOperations.TypedTuple<Object>> fromZset = redisTemplate.opsForZSet().reverseRangeWithScores(ElsConstant.HOT_WORD_DATABASE, 0, 5);
        // log.info("redis查询出来：{}",fromZset.size());
        /*if(fromZset.size() >= 5) {
            List<HotWord> lists = new ArrayList<>();
            //遍历
            Iterator<ZSetOperations.TypedTuple<Object>> iterator = fromZset.iterator();
            while (iterator.hasNext()) {
                ZSetOperations.TypedTuple<Object> next = iterator.next();
                log.info("当前的key的值为：{}", next.getValue());
                int score = (int) next.getScore().doubleValue();
                HotWord hotWord = new HotWord();
                hotWord.setHotWord((String) next.getValue());
                hotWord.setHotWordCount(score);
                lists.add(hotWord);
            }
            return lists;
        }else {*/
            for (HotWord key : list) {
                log.info("key:" + key.getId() + "value:" + key.getHotWord() + "score:" + key.getHotWordCount());
                // redisTemplate.opsForZSet().add(ElsConstant.HOT_WORD_DATABASE,key.getHotWord(),key.getHotWordCount());
            }
            return list;
    }

    @Override
    public List<GoodsItem> queryNewProduct() {
        return newProductApi.queryNewProduct();
    }



    @Override
    public List<ElasticsearchGoodsResult> querySelectGoodsItemByKeyword(String keyword, Integer pageNo, Integer pageSize) {
            List<GoodsItem> goodsItems = goodsItemApi.selectGoodsItemByKeyWord(keyword, pageNo, pageSize);
            List<ElasticsearchGoodsResult> elasticsearchGoodsResults = new ArrayList<>();
            for (int i = 0 ;i < goodsItems.size();i++){
                ElasticsearchGoodsResult goodsResult = new ElasticsearchGoodsResult();
                goodsResult.setGoodsId(goodsItems.get(i).getGoodsId());
                goodsResult.setGoodsName(goodsItems.get(i).getGoodsName());
                goodsResult.setGoodsPrice(goodsItems.get(i).getGoodsPrice());
                goodsResult.setGoodsTitle(goodsItems.get(i).getGoodsTitle());
                elasticsearchGoodsResults.add(goodsResult);
            }

        return elasticsearchGoodsResults;
    }

    @Override
    public void saveGoodsItemToElasticsearch(List<ElasticsearchGoodsResult> elasticsearchGoodsResults) {
        // 保存数据到elasticsearch
        BulkRequest bulkRequest = new BulkRequest();
        // 设置超时时间
        bulkRequest.timeout("10s");
        for (ElasticsearchGoodsResult elasticsearchGoodsResult : elasticsearchGoodsResults){
            bulkRequest.add(
                    new IndexRequest(ElsConstant.ElS_SEARCH_INDEX).id(elasticsearchGoodsResult.getGoodsId())
                    .source(JSON.toJSONString(elasticsearchGoodsResult), XContentType.JSON)
            );
        }
        try {
            //发送请求
            BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
            //获取是否失败标志
            log.info("------ 添加数据到elastic：{}",bulk.hasFailures());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public HotWord queryKeyWordIsHave(String keyword) {
        return hotWordApi.querySelectHotWord(keyword);
    }


}
